package etcd

import (
	"context"
	"fmt"
	"go.etcd.io/etcd/clientv3"
	"time"
)

func GetClient() *clientv3.Client {
	cli, err := clientv3.New(clientv3.Config{
		Endpoints:   []string{"127.0.0.1:2379"},
		DialTimeout: 10 * time.Second,
	})

	if err != nil {
		panic(err)
	}

	return cli
}

//get
func Get(a string) (string, error) {
	c := GetClient()

	resp, err := c.Get(context.Background(), a)
	if err != nil {
		return "", err
	}

	kvs := resp.Kvs
	if len(kvs) == 0 {
		return "", nil
	}
	return string(resp.Kvs[0].Value), nil
}

func GetPrefix(pre string) (map[string]string, error) {
	c := GetClient()

	resp, err := c.Get(context.Background(), pre, clientv3.WithPrefix())
	if err != nil {
		return nil, err
	}

	m := map[string]string{}
	for _, kv := range resp.Kvs {
		m[string(kv.Key)] = string(kv.Value)
	}

	return m, nil
}

//put
func Put(key string, value string) error {
	c := GetClient()

	resp, err := c.Put(context.Background(), key, value, clientv3.WithPrevKV())
	if err != nil {
		return err
	}
	fmt.Println("prev key value=" + resp.PrevKv.String())
	return nil
}

//put
func PutWithLease(key string, value string, id clientv3.LeaseID) error {
	c := GetClient()

	_, err := c.Put(context.Background(), key, value, clientv3.WithLease(id))
	if err != nil {
		return err
	}
	return nil
}
func Delete(key string) error {
	c := GetClient()

	_, err := c.Delete(context.Background(), key, clientv3.WithPrevKV())
	if err != nil {
		return err
	}
	return nil
}

//watch
type Processor func(<-chan clientv3.WatchResponse)

func Watch(key string, f Processor) {
	c := GetClient()

	channel := c.Watch(context.Background(), key)
	f(channel)
}

//观测key
func Watch1(key string, clientID string) {
	Watch(key, func(ch <-chan clientv3.WatchResponse) {
		for resp := range ch {
			for _, ev := range resp.Events {
				fmt.Printf("client: %s, Type: %s Key:%s Value:%s\n", clientID, ev.Type, ev.Kv.Key, ev.Kv.Value)
			}
		}
	})
}

//创建Lease
func CreateLease(t time.Duration) (id clientv3.LeaseID, err error) {
	c := GetClient()

	seconds := t.Seconds()
	//创建租约 约定ttl
	resp, err := c.Grant(context.Background(), int64(seconds))
	if err != nil {
		return -1, err
	}

	return resp.ID, nil
}

//续约
func KeepAlive(id clientv3.LeaseID) (<-chan *clientv3.LeaseKeepAliveResponse, error) {
	c := GetClient()
	ch, err := c.KeepAlive(context.Background(), id)
	if err != nil {
		return nil, err
	}

	return ch, nil
}

func Lease() (clientv3.LeaseID, error) {
	c := GetClient()

	resp, err := c.Grant(context.Background(), 3)
	checkError(err)

	leaseId := resp.ID
	ch, err := c.KeepAlive(context.Background(), leaseId)

	go func() {
		for value := range ch {
			fmt.Println(value)
		}
	}()

	return leaseId, nil
}
